package com.example.demo.config.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.springframework.util.StreamUtils;

import com.mysql.cj.util.StringUtils;

/**
 * 从请求体中获取参数请求包装类
 * 
 * @author  huxing
 * @version  [版本号, 2020年3月18日]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper
{
    
    private byte[] requestBody = null;//用于将流保存下来
    
    private Map<String, List<String>> headers = new HashMap<String, List<String>>();
    
    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request)
        throws IOException
    {
        super(request);
        requestBody = StreamUtils.copyToByteArray(request.getInputStream());
        Enumeration<String> names = request.getHeaderNames();
        while (names.hasMoreElements())
        {
            String name = names.nextElement();
            headers.put(name, Collections.list(request.getHeaders(name)));
        }
    }
    
    //header的操作
    public void setHeader(String key, String value)
    {
        if (!StringUtils.isNullOrEmpty(value))
        {
            List<String> list = new ArrayList<String>();
            list.add(value);
            headers.put(key, list);
        }
    }
    
    @Override
    public long getDateHeader(String name)
    {
        String value = getHeader(name);
        if (value == null)
        {
            return -1;
        }
        long date = FastHttpDateFormat.parseDate(value);
        if (date == -1)
        {
            throw new IllegalArgumentException(value);
        }
        return date;
    }
    
    @Override
    public String getHeader(String name)
    {
        Map.Entry<String, List<String>> header = getHeaderEntry(name);
        if (header == null || header.getValue() == null || header.getValue().isEmpty())
        {
            return null;
        }
        return header.getValue().get(0);
    }
    
    protected Map.Entry<String, List<String>> getHeaderEntry(String name)
    {
        for (Map.Entry<String, List<String>> entry : headers.entrySet())
        {
            if (entry.getKey().equalsIgnoreCase(name))
            {
                return entry;
            }
        }
        return null;
    }
    
    @Override
    public Enumeration<String> getHeaderNames()
    {
        return Collections.enumeration(headers.keySet());
    }
    
    @Override
    public Enumeration<String> getHeaders(String name)
    {
        Map.Entry<String, List<String>> header = getHeaderEntry(name);
        if (header == null || header.getValue() == null)
        {
            return Collections.enumeration(Collections.<String> emptyList());
        }
        return Collections.enumeration(header.getValue());
    }
    
    @Override
    public int getIntHeader(String name)
    {
        String value = getHeader(name);
        if (value == null)
        {
            return -1;
        }
        return Integer.parseInt(value);
    }
    
    @Override
    public ServletInputStream getInputStream()
        throws IOException
    {
        
        final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
        
        return new ServletInputStream()
        {
            
            @Override
            public int read()
                throws IOException
            {
                return bais.read();
            }
            
            @Override
            public boolean isFinished()
            {
                return false;
            }
            
            @Override
            public boolean isReady()
            {
                return false;
            }
            
            @Override
            public void setReadListener(ReadListener readListener)
            {
                
            }
        };
    }
    
    @Override
    public BufferedReader getReader()
        throws IOException
    {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}